package util ;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import junit.framework.Assert;
import junit.framework.TestCase;

/***/
public class HierarchicalSetTest extends TestCase
{
	private static int CHILD = 1 ;
	private static final Set<Integer> emptySet = new TreeSet<Integer>() ;
	private static int GRANDCHILD = 2 ;

	private static int PARENT = 0 ;
	private final Integer[][] elementArray ; // used to initialize objects
	private final Set<Integer>[] initialElementSet ; // used to initialize objects

	private final Set<Integer>[] unifiedElementSet ; // used as expected value

	/**
	 */
	@SuppressWarnings("unchecked")
	public HierarchicalSetTest()
	{
		super() ;
		this.elementArray = new Integer[][]
		{
		{ 1, 2, 3, 4 },
		{ 5, 6, 7 },
		{ 8, 9 } } ;
		this.initialElementSet = new Set[this.elementArray.length] ;
		this.unifiedElementSet = new Set[this.elementArray.length] ;
		for (int i = 0 ; i < this.elementArray.length ; i++)
		{
			this.initialElementSet[i] = this.setFromElementsArray(i) ;
			this.unifiedElementSet[i] = new HashSet<Integer>(this.initialElementSet[i]) ;
		}
		for (int i = 1 ; i < this.elementArray.length ; i++)
		{
			this.unifiedElementSet[i].addAll(this.unifiedElementSet[i - 1]) ;
		}
	}

	/**
	 * Test method for {@link util.HierarchicalSet#add(java.lang.Object)}.
	 */
	public void testAdd()
	{
		boolean added ;
		final HierarchicalSet<Integer>[] set = this.buildHierarchy() ;

		added = set[HierarchicalSetTest.GRANDCHILD].add(10) ;
		Assert.assertTrue(added) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(10)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(10)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(10)) ;

		added = set[HierarchicalSetTest.GRANDCHILD].add(9) ;
		Assert.assertFalse(added) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(9)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(9)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(9)) ;

		added = set[HierarchicalSetTest.CHILD].add(7) ;
		Assert.assertFalse(added) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(7)) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].contains(7)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(7)) ;

		added = set[HierarchicalSetTest.CHILD].add(9) ;
		Assert.assertTrue(added) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(9)) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].contains(9)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(9)) ;

		added = set[HierarchicalSetTest.PARENT].add(1) ;
		Assert.assertFalse(added) ;
		Assert.assertTrue(set[HierarchicalSetTest.PARENT].contains(1)) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].contains(1)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(1)) ;

		added = set[HierarchicalSetTest.PARENT].add(13) ;
		Assert.assertTrue(added) ;
		Assert.assertTrue(set[HierarchicalSetTest.PARENT].contains(13)) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].contains(13)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(13)) ;
	}

	/**
	 * Test method for {@link util.HierarchicalSet#addAll(java.util.Collection)}.
	 */
	public void testAddAll()
	{
		final Set<Integer>[] additionalSets = this.getAdditionalSets() ;

		this.testSetAddition(additionalSets[0], true, true, true) ;
		this.testSetAddition(additionalSets[1], true, true, true) ;
		this.testSetAddition(additionalSets[2], true, true, true) ;
		this.testSetAddition(additionalSets[3], false, true, true) ;
		this.testSetAddition(additionalSets[4], false, true, true) ;
		this.testSetAddition(additionalSets[5], false, false, true) ;
		this.testSetAddition(additionalSets[6], false, false, true) ;
		this.testSetAddition(additionalSets[7], false, false, true) ;
		this.testSetAddition(additionalSets[8], false, false, true) ;
		this.testSetAddition(additionalSets[9], false, false, false) ;
	}

	/**
	 * Test method for {@link util.HierarchicalSet#clear()}.
	 */
	public void testClear()
	{
		HierarchicalSet<Integer>[] set ;

		set = this.buildHierarchy() ;
		set[HierarchicalSetTest.GRANDCHILD].clear() ;
		Assert.assertEquals(HierarchicalSet.emptySet(), set[HierarchicalSetTest.GRANDCHILD].getParent()) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].isEmpty()) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].isEmpty()) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].isEmpty()) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].isEmpty()) ;

		set = this.buildHierarchy() ;
		set[HierarchicalSetTest.CHILD].clear() ;
		Assert.assertEquals(HierarchicalSet.emptySet(), set[HierarchicalSetTest.CHILD].getParent()) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].isEmpty()) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].isEmpty()) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].isEmpty()) ;

		set = this.buildHierarchy() ;
		set[HierarchicalSetTest.PARENT].clear() ;
		Assert.assertEquals(HierarchicalSet.emptySet(), set[HierarchicalSetTest.PARENT].getParent()) ;
		Assert.assertTrue(set[HierarchicalSetTest.PARENT].isEmpty()) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].isEmpty()) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].isEmpty()) ;
	}

	/**
	 * Test method for {@link util.HierarchicalSet#HierarchicalSet(java.util.Collection)}. Test method for
	 * {@link util.HierarchicalSet#HierarchicalSet(Object...)}. Test method for
	 * {@link util.HierarchicalSet#HierarchicalSet(java.util.Set, java.util.Collection)}. Test method for
	 * {@link util.HierarchicalSet#HierarchicalSet(java.util.Set, Object...)}.
	 */
	public void testConstructors()
	{
		// parent, array
		HierarchicalSet<Integer> parent1 ;
		parent1 = new HierarchicalSet<Integer>() ;
		Assert.assertEquals(HierarchicalSetTest.emptySet, parent1) ;
		Assert.assertEquals(HierarchicalSet.emptySet(), parent1.getParent()) ;
		parent1 = new HierarchicalSet<Integer>(1, 2, 3, 4) ;
		Assert.assertEquals(this.unifiedElementSet[HierarchicalSetTest.PARENT], parent1) ;
		Assert.assertEquals(HierarchicalSet.emptySet(), parent1.getParent()) ;
		final HierarchicalSet<Integer> parent2 = new HierarchicalSet<Integer>(parent1) ;
		Assert.assertEquals(parent1, parent2) ;
		Assert.assertEquals(HierarchicalSet.emptySet(), parent2.getParent()) ;

		// parent, collection
		HierarchicalSet<Integer> parent3 ;
		parent3 = new HierarchicalSet<Integer>(new TreeSet<Integer>()) ;
		Assert.assertEquals(HierarchicalSetTest.emptySet, parent3) ;
		Assert.assertEquals(HierarchicalSet.emptySet(), parent3.getParent()) ;
		parent3 = new HierarchicalSet<Integer>(new TreeSet<Integer>(
			this.initialElementSet[HierarchicalSetTest.PARENT])) ;
		Assert.assertEquals(this.unifiedElementSet[HierarchicalSetTest.PARENT], parent3) ;
		Assert.assertEquals(HierarchicalSet.emptySet(), parent3.getParent()) ;
		final HierarchicalSet<Integer> parent4 = new HierarchicalSet<Integer>(parent3) ;
		Assert.assertEquals(parent3, parent4) ;
		Assert.assertEquals(HierarchicalSet.emptySet(), parent4.getParent()) ;

		// child, array
		HierarchicalSet<Integer> child1 ;
		// not testing empty arg list
		child1 = new HierarchicalSet<Integer>(parent1, 5, 6, 7) ;
		Assert.assertEquals(this.unifiedElementSet[HierarchicalSetTest.CHILD], child1) ;
		Assert.assertSame(parent1, child1.getParent()) ;
		// not testing empty arg list

		// child, collection
		HierarchicalSet<Integer> child3 ;
		child3 = new HierarchicalSet<Integer>(parent3, HierarchicalSetTest.emptySet) ;
		Assert.assertEquals(parent3, child3) ;
		Assert.assertSame(parent3, child3.getParent()) ;
		child3 = new HierarchicalSet<Integer>(parent3, this.initialElementSet[HierarchicalSetTest.CHILD]) ;
		Assert.assertEquals(this.unifiedElementSet[HierarchicalSetTest.CHILD], child3) ;
		Assert.assertSame(parent3, child3.getParent()) ;
		// not testing empty arg list
	}

	/**
	 * tests that overlapping element still show up only once.
	 * Test method for {@link util.HierarchicalSet#iterator()}.
	 */
	public void testConstructorsElementOverlap()
	{
		final HierarchicalSet<Integer> empty = new HierarchicalSet<Integer>() ;
		final HierarchicalSet<Integer> set1 = new HierarchicalSet<Integer>(empty, 1, 2, 3, 4, 5) ;
		final HierarchicalSet<Integer> set2 = new HierarchicalSet<Integer>(set1, 2, 4, 6, 8) ;
		final HierarchicalSet<Integer> set3 = new HierarchicalSet<Integer>(set2, 3, 6, 9, 12) ;

		Assert.assertEquals(new HierarchicalSet<Integer>(), empty) ;
		Assert.assertEquals(new HierarchicalSet<Integer>(1, 2, 3, 4, 5), set1) ;
		Assert.assertEquals(new HierarchicalSet<Integer>(1, 2, 3, 4, 5, 6, 8), set2) ;
		Assert.assertEquals(new HierarchicalSet<Integer>(1, 2, 3, 4, 5, 6, 8, 9, 12), set3) ;

		final Set<Integer> set3Clone = new HashSet<Integer>() ;
		final Iterator<Integer> i = set3.iterator() ;
		while (i.hasNext())
		{
			final Integer n = i.next() ;
			Assert.assertFalse(set3Clone.contains(n)) ;
			set3Clone.add(n) ;
		}
		Assert.assertEquals(set3, set3Clone) ;
	}

	/**
	 * Test method for {@link util.HierarchicalSet#contains(java.lang.Object)}.
	 */
	public void testContains()
	{
		final HierarchicalSet<Integer> empty = new HierarchicalSet<Integer>() ;
		Assert.assertFalse(empty.contains(1)) ;
		Assert.assertFalse(empty.contains(3)) ;

		final HierarchicalSet<Integer> parent = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.PARENT]) ;
		Assert.assertTrue(parent.contains(1)) ;
		Assert.assertTrue(parent.contains(3)) ;
		Assert.assertFalse(parent.contains(5)) ;
		Assert.assertFalse(parent.contains(7)) ;

		final HierarchicalSet<Integer> child = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.CHILD]) ;
		Assert.assertTrue(child.contains(1)) ;
		Assert.assertTrue(child.contains(3)) ;
		Assert.assertTrue(child.contains(5)) ;
		Assert.assertTrue(child.contains(7)) ;
		Assert.assertFalse(child.contains(9)) ;
		Assert.assertFalse(child.contains(11)) ;

		final HierarchicalSet<Integer> grandchild = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.GRANDCHILD]) ;
		Assert.assertTrue(grandchild.contains(1)) ;
		Assert.assertTrue(grandchild.contains(3)) ;
		Assert.assertTrue(grandchild.contains(5)) ;
		Assert.assertTrue(grandchild.contains(7)) ;
		Assert.assertTrue(grandchild.contains(9)) ;
		Assert.assertFalse(grandchild.contains(11)) ;
		Assert.assertFalse(grandchild.contains(13)) ;
	}

	/**
	 * Test method for {@link util.HierarchicalSet#containsAll(java.util.Collection)}.
	 */
	public void testContainsAll()
	{
		final Set<Integer>[] additionalSets = this.getAdditionalSets() ;

		this.testGroupContainment(additionalSets[0], true, true, true) ;
		this.testGroupContainment(additionalSets[1], true, true, true) ;
		this.testGroupContainment(additionalSets[2], true, true, true) ;
		this.testGroupContainment(additionalSets[3], false, true, true) ;
		this.testGroupContainment(additionalSets[4], false, true, true) ;
		this.testGroupContainment(additionalSets[5], false, false, true) ;
		this.testGroupContainment(additionalSets[6], false, false, true) ;
		this.testGroupContainment(additionalSets[7], false, false, true) ;
		this.testGroupContainment(additionalSets[8], false, false, true) ;
	}

	/**
	 * Test method for {@link util.HierarchicalSet#equals(java.lang.Object)}. Test method for
	 * {@link util.HierarchicalSet#hashCode()}.
	 */
	public void testEqualsAndHashCode()
	{
		final HierarchicalSet<Integer> parent1 = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.PARENT]) ;
		final HierarchicalSet<Integer> parent2 = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.PARENT]) ;
		final HierarchicalSet<Integer> child1 = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.CHILD]) ;
		final HierarchicalSet<Integer> child2 = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.CHILD]) ;
		final HierarchicalSet<Integer> grandchild1 = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.GRANDCHILD]) ;
		final HierarchicalSet<Integer> grandchild2 = new HierarchicalSet<Integer>(
			this.unifiedElementSet[HierarchicalSetTest.GRANDCHILD]) ;
		final HierarchicalSet<Integer> set1 = new HierarchicalSet<Integer>(1, 3, 5, 7) ;
		final HierarchicalSet<Integer> set2 = new HierarchicalSet<Integer>(set1, 2, 4, 6) ;

		// refelxiveness
		Assert.assertTrue(parent1.equals(parent1)) ;
		Assert.assertTrue(child1.equals(child1)) ;
		Assert.assertTrue(grandchild1.equals(grandchild1)) ;

		// symmetry
		Assert.assertTrue(parent1.equals(parent2)) ;
		Assert.assertTrue(parent2.equals(parent1)) ;
		Assert.assertTrue(parent1.hashCode() == parent2.hashCode()) ;
		Assert.assertTrue(child1.equals(child2)) ;
		Assert.assertTrue(child2.equals(child1)) ;
		Assert.assertTrue(child1.hashCode() == child2.hashCode()) ;
		Assert.assertTrue(grandchild1.equals(grandchild2)) ;
		Assert.assertTrue(grandchild2.equals(grandchild1)) ;
		Assert.assertTrue(grandchild1.hashCode() == grandchild2.hashCode()) ;

		// difference
		Assert.assertFalse(parent1.equals(child1)) ;
		Assert.assertFalse(child1.equals(grandchild1)) ;
		Assert.assertFalse(parent1.equals(set1)) ;
		Assert.assertFalse(child1.equals(set1)) ;
		Assert.assertFalse(grandchild1.equals(set1)) ;
		// different siblings
		Assert.assertFalse(child1
			.equals(new HierarchicalSet<Integer>(parent1, HierarchicalSetTest.emptySet))) ;
		Assert.assertFalse(child1.equals(new HierarchicalSet<Integer>(parent1, 10, 11, 12))) ;
		Assert.assertFalse(child1.equals(new HierarchicalSet<Integer>(parent1, 2, 4, 6))) ;

		// deep equality (element-wise)
		Assert.assertFalse(parent1.equals(set1)) ;
		Assert.assertFalse(set2.equals(parent1)) ;
		Assert.assertTrue(child1.equals(set2)) ;
		Assert.assertTrue(set2.equals(child1)) ;
		Assert.assertTrue(child1.hashCode() == set2.hashCode()) ;
	}

	/**
	 * Test method for {@link util.HierarchicalSet#remove(Object)}.
	 */
	public void testRemove()
	{
		boolean removed ;
		HierarchicalSet<Integer>[] set ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.GRANDCHILD].remove(8) ;
		Assert.assertTrue(removed) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(8)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(8)) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].contains(8)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.GRANDCHILD].remove(11) ;
		Assert.assertFalse(removed) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(11)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(11)) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].contains(11)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.CHILD].remove(8) ;
		Assert.assertFalse(removed) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(8)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(8)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(8)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.CHILD].remove(5) ;
		Assert.assertTrue(removed) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(5)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(5)) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].contains(5)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.PARENT].remove(9) ;
		Assert.assertFalse(removed) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(9)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(9)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].contains(9)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.PARENT].remove(2) ;
		Assert.assertTrue(removed) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(2)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(2)) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].contains(2)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.CHILD].remove(1) ;
		Assert.assertTrue(removed) ;
		Assert.assertTrue(set[HierarchicalSetTest.PARENT].contains(1)) ;
		Assert.assertFalse(set[HierarchicalSetTest.CHILD].contains(1)) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].contains(1)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.GRANDCHILD].remove(3) ;
		Assert.assertTrue(removed) ;
		Assert.assertTrue(set[HierarchicalSetTest.PARENT].contains(3)) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].contains(3)) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].contains(3)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.GRANDCHILD].remove(7) ;
		Assert.assertTrue(removed) ;
		Assert.assertFalse(set[HierarchicalSetTest.PARENT].contains(7)) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].contains(7)) ;
		Assert.assertFalse(set[HierarchicalSetTest.GRANDCHILD].contains(7)) ;

		// check that duplicates remain.
		final Set<Integer> s1 = new HashSet<Integer>() ;
		s1.add(4) ;
		final Set<Integer> s2 = new HierarchicalSet<Integer>(s1, 4) ;

		removed = s2.remove(4) ;
		Assert.assertTrue(removed) ;
		Assert.assertFalse(s2.isEmpty()) ;

	}

	/**
	 * Test method for {@link util.HierarchicalSet#removeAll(java.util.Collection)}.
	 */
	public void testRemoveAll()
	{
		final Set<Integer>[] additionalSets = this.getAdditionalSets() ;

		//this.testSetSubtraction(additionalSets[0], true, true, true) ;
		this.testSetSubtraction(additionalSets[1], true, true, true) ;
		this.testSetSubtraction(additionalSets[2], true, true, true) ;
		this.testSetSubtraction(additionalSets[3], true, true, true) ;
		this.testSetSubtraction(additionalSets[4], false, true, true) ;
		this.testSetSubtraction(additionalSets[5], false, true, true) ;
		this.testSetSubtraction(additionalSets[6], false, false, true) ;
		this.testSetSubtraction(additionalSets[7], true, true, true) ;
		this.testSetSubtraction(additionalSets[8], true, true, true) ;
		this.testSetSubtraction(additionalSets[9], false, true, true) ;
	}

	@SuppressWarnings("unchecked")
	private HierarchicalSet<Integer>[] buildHierarchy()
	{
		final HierarchicalSet<Integer>[] set ;
		set = new HierarchicalSet[3] ;
		set[0] = new HierarchicalSet<Integer>(this.initialElementSet[0]) ;
		for (int i = 1 ; i < set.length ; i++)
		{
			set[i] = new HierarchicalSet<Integer>(set[i - 1], this.initialElementSet[i]) ;
		}
		return set ;
	}

	@SuppressWarnings("unchecked")
	private Set<Integer>[] getAdditionalSets()
	{
		final Integer[][] initialAdditionalSets =
		{ {},
		{ 1 },
		{ 1, 3 },
		{ 1, 3, 5 },
		{ 5, 6 },
		{ 7, 8 },
		{ 9 },
		{ 1, 9 },
		{ 1, 6, 8 },
		{ 7, 16 } } ;
		final Set<Integer>[] additionalSets = new Set[initialAdditionalSets.length] ;
		for (int i = 0 ; i < initialAdditionalSets.length ; i++)
		{
			additionalSets[i] = new TreeSet<Integer>(Arrays.asList(initialAdditionalSets[i])) ;
		}
		return additionalSets ;
	}

	private TreeSet<Integer> setFromElementsArray(final int i)
	{
		return new TreeSet<Integer>(Arrays.asList(this.elementArray[i])) ;
	}

	private void testGroupContainment(final Set<Integer> setToTest, final boolean containedInParent,
		final boolean containedInChild, final boolean containedInGrandchild)
	{
		final HierarchicalSet<Integer>[] set = this.buildHierarchy() ;
		Assert.assertEquals(containedInParent, set[HierarchicalSetTest.PARENT].containsAll(setToTest)) ;
		Assert.assertEquals(containedInChild, set[HierarchicalSetTest.CHILD].containsAll(setToTest)) ;
		Assert.assertEquals(containedInGrandchild, set[HierarchicalSetTest.GRANDCHILD]
			.containsAll(setToTest)) ;
	}

	private void testSetAddition(final Set<Integer> setToAdd, final boolean containedInParent,
		final boolean containedInChild, final boolean containedInGrandchild)
	{
		boolean added ;
		HierarchicalSet<Integer>[] set ;

		set = this.buildHierarchy() ;
		added = set[HierarchicalSetTest.PARENT].addAll(setToAdd) ;
		Assert.assertEquals(!containedInParent, added) ;
		Assert.assertTrue(set[HierarchicalSetTest.PARENT].containsAll(setToAdd)) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].containsAll(setToAdd)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].containsAll(setToAdd)) ;

		set = this.buildHierarchy() ;
		added = set[HierarchicalSetTest.CHILD].addAll(setToAdd) ;
		Assert.assertEquals(!containedInChild, added) ;
		Assert.assertTrue(set[HierarchicalSetTest.CHILD].containsAll(setToAdd)) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].containsAll(setToAdd)) ;

		set = this.buildHierarchy() ;
		added = set[HierarchicalSetTest.GRANDCHILD].addAll(setToAdd) ;
		Assert.assertEquals(!containedInGrandchild, added) ;
		Assert.assertTrue(set[HierarchicalSetTest.GRANDCHILD].containsAll(setToAdd)) ;
	}

	private void testSetSubtraction(final Set<Integer> setToSubtract, final boolean containedInParent,
		final boolean containedInChild, final boolean containedInGrandchild)
	{
		boolean removed ;
		HierarchicalSet<Integer>[] set ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.PARENT].removeAll(setToSubtract) ;
		Assert.assertEquals(containedInParent, removed) ;
		Assert.assertTrue(HierarchicalSet.areDisjoint(set[HierarchicalSetTest.PARENT], setToSubtract)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.CHILD].removeAll(setToSubtract) ;
		Assert.assertEquals(containedInChild, removed) ;
		Assert.assertTrue(HierarchicalSet.areDisjoint(set[HierarchicalSetTest.CHILD], setToSubtract)) ;

		set = this.buildHierarchy() ;
		removed = set[HierarchicalSetTest.GRANDCHILD].removeAll(setToSubtract) ;
		Assert.assertEquals(containedInGrandchild, removed) ;
		Assert.assertTrue(HierarchicalSet.areDisjoint(set[HierarchicalSetTest.GRANDCHILD], setToSubtract)) ;
	}
}
